// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod mresult;
mod mutils;
use mresult::Mresult;
use mutils::sys_info::SystemInfo;
use tauri::Window;
use components::{
  sea_orm::{DatabaseConnection,Database},
  PermissionApi
};

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
async fn docom(method:&str,data: &str) -> Result<String,String> {
    match method {
        "get_sys_info" => {
          let res:Mresult<SystemInfo> = match mutils::sys_info::get_sys_info() {
            Ok(si) => Mresult::success_return_data(si),
            Err(e) => Mresult::error_return(&e)
          };
          let res_str = serde_json::to_string_pretty(&res).unwrap();
          Ok(res_str)
        },
        "set_config" => {
          let m_config:mutils::Config = serde_json::from_str(data).unwrap();
          match mutils::set_config(m_config).await {
            Ok(_) => Ok(serde_json::to_string(&Mresult::success()).unwrap()),
            Err(e) => {
              let err_str = format!("保存错误:{}",e);
              let res = Mresult::error_description(mresult::Mresult::SYS_ERROR,&err_str);
              let res_str = serde_json::to_string_pretty(&res).unwrap();
              return Ok(res_str);
            }
          }
        },
        "get_config" => {
          let m_config = mutils::get_config().await;
          match m_config {
            Ok(si) => Ok(serde_json::to_string_pretty(&Mresult::success_return_data(si)).unwrap()),
            Err(_) => {
              let err_str = String::from("获取配置文件失败");
              let res = Mresult::error_description(mresult::Mresult::SYS_ERROR,&err_str);
              let res_str = serde_json::to_string(&res).unwrap();
              Ok(res_str)
            }
          }
        }
        "error" => Ok(serde_json::to_string(&Mresult::error(Mresult::SYS_ERROR)).unwrap()),
        "success" => Ok(serde_json::to_string(&Mresult::success()).unwrap()),
        "return_post_data" => Ok(format!("收到的post_data:{}",data)),
        "return_sys_err" =>  Err("系统错误".to_string()),
        _ => {
          let err_str = String::from("未找到方法");
          let res = Mresult::error_description(mresult::Mresult::SYS_ERROR,&err_str);
          let res_str = serde_json::to_string(&res).unwrap();
          Ok(res_str)
        }
    }
}

#[tauri::command]
async fn do_fn_orm(state: tauri::State<'_, AppState>, method:&str,data: &str) -> Result<String, ()> {
  match state.conn {
    Some(_) => {},
    None => {
      let err_str = String::from("未连接数据库");
      let res = Mresult::error_description(mresult::Mresult::SYS_ERROR,&err_str);
      let res_str = serde_json::to_string_pretty(&res).unwrap();
      return Ok(res_str);
    }
  }
  let conn = state.conn.clone().unwrap();
  match method {
    "auth/add_permission" => {
      let res:Mresult<()> = match PermissionApi::add_permission(&conn, data).await {
        Ok(_) => Mresult::success(),
        Err(e) =>Mresult::error_description(mresult::Mresult::SYS_ERROR,&e.to_string())
      };
      let res_str = serde_json::to_string_pretty(&res).unwrap();
      Ok(res_str)
    },
    "auth/update_permission" => {
      let res:Mresult<()> = match PermissionApi::update_permission(&conn, data).await {
        Ok(_) => Mresult::success(),
        Err(e) =>Mresult::error_description(mresult::Mresult::SYS_ERROR,&e.to_string())
      };
      let res_str = serde_json::to_string_pretty(&res).unwrap();
      Ok(res_str)
    },
    _ => {
      let err_str = String::from("未找到方法");
      let res = Mresult::error_description(mresult::Mresult::SYS_ERROR,&err_str);
      let res_str = serde_json::to_string(&res).unwrap();
      Ok(res_str)
    }
}
}

// the payload type must implement `Serialize` and `Clone`.
#[derive(Clone, serde::Serialize)]
struct Payload {
  message: String,
}

// init a background process on the command, and emit periodic events only to the window that used the command
#[tauri::command]
fn init_process(window: Window) {
  //持续循环推送给监听线程
  std::thread::spawn(move || 
    loop {
      window.emit("event-name", Payload { message: "Tauri is awesome!".into() }).unwrap();
      std::thread::sleep(std::time::Duration::from_millis(500));
    }
  );
}
//用于托管数据库链接全程序线程下统一管理
#[derive(Clone)]
struct AppState {
    conn: Option<DatabaseConnection>,
}

#[tokio::main]
async fn main() {
  //初始化配置文件
  //env::set_var("RUST_LOG", "debug");
  //全局跟踪用于调试正式封装可删除
  //tracing_subscriber::fmt::init();
  //dotenv::dotenv().ok();
  //创建配置文件
  let _ = mutils::config_fs_init().await;
  let m_config = match mutils::get_config().await {
      Ok(si) => si,
      Err(_) =>{ 
        let config = mutils::Config{
          url : String::from("postgres://postgres:abcd1234@192.168.2.8:5432/fui"),
          sql_type:mutils::SqlType::Postgres
        };
        config
      },
  };
  //读取配置文件中的数据库链接
  let db_url = m_config.url;
  println!("{}",db_url);
  let conn = match Database::connect(db_url).await {
      Ok(si) => Some(si),
      Err(_) => None,
  };
  //创建全局托管类托管类托管数据库链接
  let state = AppState { conn };
  
  tauri::Builder::default()
    .manage(state)//全局托管数据库链接
    .invoke_handler(tauri::generate_handler![docom,init_process,do_fn_orm])
    .run(tauri::generate_context!())
    .expect("启动错误");
}
